package com.copd.controller;

import com.copd.common.ApiResponse;
import com.copd.dto.LogCreateRequest;
import com.copd.dto.OperationLogQueryRequest;
import com.copd.service.DoctorOperationLogService;
import com.copd.util.JwtUtil;
import com.copd.util.TimeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Api(tags = "医生操作日志接口", description = "医生操作日志相关的接口")
@RestController
@RequestMapping("/api/operation-logs")
public class DoctorOperationLogController {

    private static final Logger logger = LoggerFactory.getLogger(DoctorOperationLogController.class);

    @Autowired
    private DoctorOperationLogService logService;
    
    @Autowired
    private JwtUtil jwtUtil;

    @ApiOperation(value = "记录操作日志", notes = "记录医生对患者的操作日志。\n" +
            "注意：当记录患者相关操作时，应同时记录与患者相关的所有表的变更，包括：\n" +
            "- patient_info（患者基本信息）\n" +
            "- diagnosis_records（诊断记录）\n" +
            "- examination_items（检查项目）\n" +
            "- treatment_plans（治疗方案）\n" +
            "- discharge_records（出院建议）\n\n" +
            "建议使用 OperationLogHelper 工具类来创建包含所有相关表的日志请求。\n" +
            "示例：\n" +
            "```java\n" +
            "// 创建包含所有患者相关表的日志请求\n" +
            "LogCreateRequest request = OperationLogHelper.createFullPatientLogRequest(\n" +
            "    doctorId,\n" +
            "    patientId,\n" +
            "    \"修改\",\n" +
            "    ipAddress,\n" +
            "    deviceInfo,\n" +
            "    patientInfoDetailJson,   // 患者基本信息变更，可为null\n" +
            "    diagnosisDetailJson,     // 诊断记录变更，可为null\n" +
            "    examinationDetailJson,   // 检查项目变更，可为null\n" +
            "    treatmentDetailJson,     // 治疗方案变更，可为null\n" +
            "    dischargeDetailJson      // 出院建议变更，可为null\n" +
            ");\n" +
            "```\n" +
            "或者直接调用日志助手的便捷方法：\n" +
            "```java\n" +
            "OperationLogHelper.logFullPatientOperation(\n" +
            "    logService,\n" +
            "    doctorId,\n" +
            "    patientId,\n" +
            "    \"修改\",\n" +
            "    ipAddress,\n" +
            "    deviceInfo,\n" +
            "    patientInfoObject,       // 患者基本信息对象，可为null\n" +
            "    diagnosisObject,         // 诊断记录对象，可为null\n" +
            "    examinationObject,       // 检查项目对象，可为null\n" +
            "    treatmentObject,         // 治疗方案对象，可为null\n" +
            "    dischargeObject          // 出院建议对象，可为null\n" +
            ");\n" +
            "```")
    @PostMapping
    public ResponseEntity<?> createLog(
            @ApiParam(value = "日志创建请求", required = true) @RequestBody LogCreateRequest request,
            HttpServletRequest servletRequest) {
        try {
            // 获取IP地址和设备信息
            String ipAddress = getClientIpAddress(servletRequest);
            String deviceInfo = servletRequest.getHeader("User-Agent");
            
            // 如果未设置医生ID，从当前用户获取
            if (request.getDoctorId() == null) {
                Integer currentUserId = getCurrentUserId(servletRequest);
                if (currentUserId != null) {
                    request.setDoctorId(currentUserId); // user_id作为doctor_id
                    logger.info("使用当前登录用户ID({})作为医生ID", currentUserId);
                } else {
                    return ResponseEntity.badRequest()
                        .body(ApiResponse.error("请提供医生ID或登录后再创建日志"));
                }
            }
            
            // 设置IP和设备信息
            request.setIpAddress(ipAddress);
            request.setDeviceInfo(deviceInfo);
            
            // 创建日志
            Integer logId = logService.createLog(request);
            
            return ResponseEntity.ok(ApiResponse.success("日志记录成功", logId));
        } catch (IllegalArgumentException e) {
            logger.error("记录操作日志参数错误", e);
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            logger.error("记录操作日志失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("系统错误：" + e.getMessage()));
        }
    }

    @ApiOperation(value = "查询操作日志", notes = "分页查询医生操作日志列表，不提供任何参数时返回所有日志")
    @GetMapping
    public ResponseEntity<?> queryLogs(
            @ApiParam(value = "医生ID (Users表中role为doctor的user_id)") @RequestParam(required = false) Integer doctorId,
            @ApiParam(value = "患者ID") @RequestParam(required = false) Integer patientId,
            @ApiParam(value = "医生姓名") @RequestParam(required = false) String doctorName,
            @ApiParam(value = "患者姓名") @RequestParam(required = false) String patientName,
            @ApiParam(value = "操作类型") @RequestParam(required = false) String operationType,
            @ApiParam(value = "操作结果") @RequestParam(required = false) Boolean operationResult,
            @ApiParam(value = "开始时间") @RequestParam(required = false) String startTime,
            @ApiParam(value = "结束时间") @RequestParam(required = false) String endTime,
            @ApiParam(value = "页码", example = "1") @RequestParam(defaultValue = "1") Integer page,
            @ApiParam(value = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size,
            HttpServletRequest servletRequest) {
        try {
            logger.info("查询操作日志，参数: doctorId={}, patientId={}, page={}, size={}", 
                      doctorId, patientId, page, size);
            
            // 构建查询请求
            OperationLogQueryRequest queryRequest = new OperationLogQueryRequest();
            queryRequest.setDoctorId(doctorId);
            queryRequest.setPatientId(patientId);
            queryRequest.setDoctorName(doctorName);
            queryRequest.setPatientName(patientName);
            queryRequest.setOperationType(operationType);
            queryRequest.setOperationResult(operationResult);
            // 时间转换处理在服务层实现
            queryRequest.setStartTime(startTime);
            queryRequest.setEndTime(endTime);
            queryRequest.setPage(page);
            queryRequest.setSize(size);
            
            // 查询日志
            Map<String, Object> result = logService.queryLogs(queryRequest);
            logger.info("查询操作日志成功，结果: {}", result != null ? "找到 " + result.get("total") + " 条记录" : "无结果");
            
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            logger.error("查询操作日志失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("系统错误：" + e.getMessage()));
        }
    }

    @ApiOperation(value = "获取日志详情", notes = "根据日志ID获取详细信息")
    @GetMapping("/{logId}")
    public ResponseEntity<?> getLogDetail(
            @ApiParam(value = "日志ID", example = "1") @PathVariable Integer logId) {
        try {
            Map<String, Object> detail = logService.getLogById(logId);
            return ResponseEntity.ok(ApiResponse.success(detail));
        } catch (IllegalArgumentException e) {
            logger.error("获取日志详情参数错误", e);
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            logger.error("获取日志详情失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("系统错误：" + e.getMessage()));
        }
    }

    @ApiOperation(value = "查询备份相关操作日志", notes = "查询影响了备份表的操作日志，如patient_info、treatment_plans等")
    @GetMapping("/backup-operations")
    public ResponseEntity<?> queryBackupLogs(
            @ApiParam(value = "医生ID") @RequestParam(required = false) Integer doctorId,
            @ApiParam(value = "患者ID") @RequestParam(required = false) Integer patientId,
            @ApiParam(value = "医生姓名") @RequestParam(required = false) String doctorName,
            @ApiParam(value = "患者姓名") @RequestParam(required = false) String patientName,
            @ApiParam(value = "操作类型") @RequestParam(required = false) String operationType,
            @ApiParam(value = "备份表名") @RequestParam(required = false) String tableName,
            @ApiParam(value = "开始时间") @RequestParam(required = false) String startTime,
            @ApiParam(value = "结束时间") @RequestParam(required = false) String endTime,
            @ApiParam(value = "页码", example = "1") @RequestParam(defaultValue = "1") Integer page,
            @ApiParam(value = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size,
            HttpServletRequest servletRequest) {
        try {
            // 构建查询请求
            OperationLogQueryRequest queryRequest = new OperationLogQueryRequest();
            queryRequest.setDoctorId(doctorId);
            queryRequest.setPatientId(patientId);
            queryRequest.setDoctorName(doctorName);
            queryRequest.setPatientName(patientName);
            queryRequest.setOperationType(operationType);
            queryRequest.setTableName(tableName); // 增加表名参数
            queryRequest.setStartTime(startTime); // 设置开始时间字符串
            queryRequest.setEndTime(endTime);     // 设置结束时间字符串
            queryRequest.setPage(page);
            queryRequest.setSize(size);
            
            // 查询日志 - 调用专门查询影响备份表的操作
            Map<String, Object> result = logService.queryBackupLogs(queryRequest);
            
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            logger.error("查询备份操作日志失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("系统错误：" + e.getMessage()));
        }
    }

    @ApiOperation(value = "查询按时间和患者分组的操作日志", notes = "分页查询医生操作日志列表，并按照操作时间和患者ID分组展示")
    @GetMapping("/grouped")
    public ResponseEntity<?> queryGroupedLogs(
            @ApiParam(value = "医生ID (Users表中role为doctor的user_id)") @RequestParam(required = false) Integer doctorId,
            @ApiParam(value = "患者ID") @RequestParam(required = false) Integer patientId,
            @ApiParam(value = "医生姓名") @RequestParam(required = false) String doctorName,
            @ApiParam(value = "患者姓名") @RequestParam(required = false) String patientName,
            @ApiParam(value = "操作类型") @RequestParam(required = false) String operationType,
            @ApiParam(value = "操作结果") @RequestParam(required = false) Boolean operationResult,
            @ApiParam(value = "开始时间") @RequestParam(required = false) String startTime,
            @ApiParam(value = "结束时间") @RequestParam(required = false) String endTime,
            @ApiParam(value = "页码", example = "1") @RequestParam(defaultValue = "1") Integer page,
            @ApiParam(value = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer size,
            HttpServletRequest servletRequest) {
        try {
            logger.info("查询分组操作日志，参数: doctorId={}, patientId={}, page={}, size={}", 
                      doctorId, patientId, page, size);
            
            // 构建查询请求
            OperationLogQueryRequest queryRequest = new OperationLogQueryRequest();
            queryRequest.setDoctorId(doctorId);
            queryRequest.setPatientId(patientId);
            queryRequest.setDoctorName(doctorName);
            queryRequest.setPatientName(patientName);
            queryRequest.setOperationType(operationType);
            queryRequest.setOperationResult(operationResult);
            queryRequest.setStartTime(startTime);
            queryRequest.setEndTime(endTime);
            queryRequest.setPage(page);
            queryRequest.setSize(size);
            
            // 查询分组日志
            Map<String, Object> result = logService.queryGroupedLogs(queryRequest);
            logger.info("查询分组操作日志成功，结果: {}", result != null ? "找到 " + result.get("total") + " 条记录" : "无结果");
            
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            logger.error("查询分组操作日志失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("系统错误：" + e.getMessage()));
        }
    }

    /**
     * 获取当前用户ID (作为医生ID使用, 即Users表中role为doctor的user_id)
     */
    private Integer getCurrentUserId(HttpServletRequest request) {
        // 1. 首先尝试从Spring Security上下文获取
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated()) {
                Object principal = authentication.getPrincipal();
                if (principal instanceof Integer) {
                    return (Integer) principal;
                }
            }
        } catch (Exception e) {
            logger.debug("无法从Security上下文获取用户ID: {}", e.getMessage());
        }
        
        // 2. 从请求属性中获取
        try {
            Object doctorIdObj = request.getAttribute("doctorId");
            if (doctorIdObj != null) {
                return (Integer) doctorIdObj;
            }
        } catch (Exception e) {
            logger.debug("无法从请求属性获取用户ID: {}", e.getMessage());
        }
        
        // 3. 从JWT令牌获取
        try {
            String authHeader = request.getHeader("Authorization");
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String token = authHeader.substring(7);
                return jwtUtil.getUserIdFromToken(token);
            }
        } catch (Exception e) {
            logger.debug("无法从JWT令牌获取用户ID: {}", e.getMessage());
        }
        
        return null;
    }

    /**
     * 获取客户端的IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
} 